{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Self Discover Pack\n",
    "\n",
    "<a href=\"https://colab.research.google.com/github/run-llama/llama_index/blob/main/llama-index-packs/llama-index-packs-self-discover/examples/self_discover.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>\n",
    "\n",
    "This LlamaPack implements [Self-Discover: Large Language Models Self-Compose Reasoning Structures](https://arxiv.org/abs/2402.03620) paper.\n",
    "\n",
    "It has two stages for the given task:\n",
    "\n",
    "1. STAGE-1:\n",
    "\n",
    "    a. SELECT: Selects subset of reasoning Modules.\n",
    "\n",
    "    b. ADAPT: Adapts selected reasoning modules to the task.\n",
    "\n",
    "    c. IMPLEMENT: It gives reasoning structure for the task.\n",
    "    \n",
    "2. STAGE-2: Uses the generated reasoning structure for the task to generate an answer.\n",
    "\n",
    "\n",
    "The implementation is inspired from the [codebase](https://github.com/catid/self-discover)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "os.environ[\"OPENAI_API_KEY\"] = \"YOUR OPENAI API KEY\"\n",
    "from llama_index.llms.openai import OpenAI\n",
    "\n",
    "llm = OpenAI(\"gpt-4\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Load / Download Pack\n",
    "\n",
    "There are two ways to use the LlamaPack.\n",
    "\n",
    "1. Do `download_llama_pack` to load the Self-Discover LlamaPack.\n",
    "2. Directly use `SelfDiscoverPack`"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Using `download_llama_pack`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.core.llama_pack import download_llama_pack\n",
    "\n",
    "SelfDiscoverPack = download_llama_pack(\"SelfDiscoverPack\", \"./self_discover_pack\")\n",
    "\n",
    "self_discover_pack = SelfDiscoverPack(verbose=True, llm=llm)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Directly use `SelfDiscoverPack`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.packs.self_discover import SelfDiscoverPack"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "self_discover_pack = SelfDiscoverPack(verbose=True, llm=llm)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Test out on some tasks"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Task\n",
    "\n",
    "Michael has 15 oranges. He gives 4 oranges to his brother and trades 3 oranges for 6 apples with his neighbor. Later in the day, he realizes some of his oranges are spoiled, so he discards 2 of them. Then, Michael goes to the market and buys 12 more oranges and 5 more apples. If Michael decides to give 2 apples to his friend, how many oranges and apples does Michael have now?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[1;3;38;2;155;135;227m> Running module input with input: \n",
      "task: Michael has 15 oranges. He gives 4 oranges to his brother and trades 3 oranges for 6 apples with his neighbor. Later in the day, he realizes some of his oranges are spoiled, so he discards 2 of them. ...\n",
      "reasoning_modules: 1. How could I devise an experiment to help solve that problem?\n",
      "2. Make a list of ideas for solving this problem, and apply them one by one to the problem to see if any progress can be made.\n",
      "3. How co...\n",
      "\n",
      "\u001b[0m\u001b[1;3;38;2;155;135;227m> Running module select_prompt_template with input: \n",
      "task: Michael has 15 oranges. He gives 4 oranges to his brother and trades 3 oranges for 6 apples with his neighbor. Later in the day, he realizes some of his oranges are spoiled, so he discards 2 of them. ...\n",
      "reasoning_modules: 1. How could I devise an experiment to help solve that problem?\n",
      "2. Make a list of ideas for solving this problem, and apply them one by one to the problem to see if any progress can be made.\n",
      "3. How co...\n",
      "\n",
      "\u001b[0m\u001b[1;3;38;2;155;135;227m> Running module select_llm with input: \n",
      "messages: Given the task: Michael has 15 oranges. He gives 4 oranges to his brother and trades 3 oranges for 6 apples with his neighbor. Later in the day, he realizes some of his oranges are spoiled, so he disc...\n",
      "\n",
      "\u001b[0m\u001b[1;3;38;2;155;135;227m> Running module adapt_prompt_template with input: \n",
      "task: Michael has 15 oranges. He gives 4 oranges to his brother and trades 3 oranges for 6 apples with his neighbor. Later in the day, he realizes some of his oranges are spoiled, so he discards 2 of them. ...\n",
      "selected_modules: assistant: 2. Make a list of ideas for solving this problem, and apply them one by one to the problem to see if any progress can be made.\n",
      "4. How can I simplify the problem so that it is easier to solv...\n",
      "\n",
      "\u001b[0m\u001b[1;3;38;2;155;135;227m> Running module adapt_llm with input: \n",
      "messages: Without working out the full solution, adapt the following reasoning modules to be specific to our task:\n",
      "2. Make a list of ideas for solving this problem, and apply them one by one to the problem to s...\n",
      "\n",
      "\u001b[0m\u001b[1;3;38;2;155;135;227m> Running module implement_prompt_template with input: \n",
      "task: Michael has 15 oranges. He gives 4 oranges to his brother and trades 3 oranges for 6 apples with his neighbor. Later in the day, he realizes some of his oranges are spoiled, so he discards 2 of them. ...\n",
      "adapted_modules: assistant: 2. Ideas for solving this problem could include: \n",
      "   - Calculating the number of oranges and apples Michael has after each transaction.\n",
      "   - Keeping a running total of the number of oranges...\n",
      "\n",
      "\u001b[0m\u001b[1;3;38;2;155;135;227m> Running module implement_llm with input: \n",
      "messages: Without working out the full solution, create an actionable reasoning structure for the task using these adapted reasoning modules:\n",
      "2. Ideas for solving this problem could include: \n",
      "   - Calculating t...\n",
      "\n",
      "\u001b[0m\u001b[1;3;38;2;155;135;227m> Running module reasoning_prompt_template with input: \n",
      "task: Michael has 15 oranges. He gives 4 oranges to his brother and trades 3 oranges for 6 apples with his neighbor. Later in the day, he realizes some of his oranges are spoiled, so he discards 2 of them. ...\n",
      "reasoning_structure: assistant: 1. Understand the problem: The problem involves multiple transactions of oranges and apples that Michael has. The goal is to find out how many oranges and apples Michael has after all these...\n",
      "\n",
      "\u001b[0m\u001b[1;3;38;2;155;135;227m> Running module reasoning_llm with input: \n",
      "messages: Using the following reasoning structure: 1. Understand the problem: The problem involves multiple transactions of oranges and apples that Michael has. The goal is to find out how many oranges and appl...\n",
      "\n",
      "\u001b[0m"
     ]
    }
   ],
   "source": [
    "task = \"Michael has 15 oranges. He gives 4 oranges to his brother and trades 3 oranges for 6 apples with his neighbor. Later in the day, he realizes some of his oranges are spoiled, so he discards 2 of them. Then, Michael goes to the market and buys 12 more oranges and 5 more apples. If Michael decides to give 2 apples to his friend, how many oranges and apples does Michael have now?\"\n",
    "output = self_discover_pack.run(task)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "assistant: 1. Understand the problem: The problem involves multiple transactions of oranges and apples that Michael has. The goal is to find out how many oranges and apples Michael has after all these transactions.\n",
      "\n",
      "2. Break down the problem: The problem can be broken down into several smaller problems, each representing a transaction. \n",
      "\n",
      "3. Plan the solution: \n",
      "   - Step 1: Calculate the number of oranges after Michael gives some to his brother and trades with his neighbor.\n",
      "   - Step 2: Calculate the number of apples after the trade.\n",
      "   - Step 3: Calculate the number of oranges after discarding the spoiled ones.\n",
      "   - Step 4: Calculate the number of oranges and apples after Michael buys more from the market.\n",
      "   - Step 5: Calculate the final number of apples after Michael gives some to his friend.\n",
      "   - Step 6: Summarize the final number of oranges and apples Michael has.\n",
      "\n",
      "4. Execute the plan: \n",
      "   - Step 1: Michael has 15 oranges - 4 oranges (given to his brother) - 3 oranges (traded with his neighbor) = 8 oranges.\n",
      "   - Step 2: Michael has 0 apples + 6 apples (from the trade) = 6 apples.\n",
      "   - Step 3: Michael has 8 oranges - 2 oranges (spoiled) = 6 oranges.\n",
      "   - Step 4: Michael has 6 oranges + 12 oranges (bought from the market) = 18 oranges and 6 apples + 5 apples (bought from the market) = 11 apples.\n",
      "   - Step 5: Michael has 11 apples - 2 apples (given to his friend) = 9 apples.\n",
      "   - Step 6: Michael has 18 oranges and 9 apples.\n",
      "\n",
      "5. Verify the solution: Michael has 18 oranges and 9 apples after all the transactions, which is the correct answer.\n"
     ]
    }
   ],
   "source": [
    "print(output)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Task\n",
    "\n",
    "Tom needs to buy ingredients for a spaghetti dinner he's planning for himself and a friend. He already has pasta at home but needs to buy tomato sauce and ground beef. At the store, tomato sauce costs $3 per jar and ground beef costs $5 per pound. Tom buys 2 jars of tomato sauce and 2 pounds of ground beef. He also picks up a loaf of bread for $2.50. If Tom pays with a $50 bill, how much change should he receive after purchasing these items?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[1;3;38;2;155;135;227m> Running module input with input: \n",
      "task: Tom needs to buy ingredients for a spaghetti dinner he's planning for himself and a friend. He already has pasta at home but needs to buy tomato sauce and ground beef. At the store, tomato sauce costs...\n",
      "reasoning_modules: 1. How could I devise an experiment to help solve that problem?\n",
      "2. Make a list of ideas for solving this problem, and apply them one by one to the problem to see if any progress can be made.\n",
      "3. How co...\n",
      "\n",
      "\u001b[0m\u001b[1;3;38;2;155;135;227m> Running module select_prompt_template with input: \n",
      "task: Tom needs to buy ingredients for a spaghetti dinner he's planning for himself and a friend. He already has pasta at home but needs to buy tomato sauce and ground beef. At the store, tomato sauce costs...\n",
      "reasoning_modules: 1. How could I devise an experiment to help solve that problem?\n",
      "2. Make a list of ideas for solving this problem, and apply them one by one to the problem to see if any progress can be made.\n",
      "3. How co...\n",
      "\n",
      "\u001b[0m\u001b[1;3;38;2;155;135;227m> Running module select_llm with input: \n",
      "messages: Given the task: Tom needs to buy ingredients for a spaghetti dinner he's planning for himself and a friend. He already has pasta at home but needs to buy tomato sauce and ground beef. At the store, to...\n",
      "\n",
      "\u001b[0m\u001b[1;3;38;2;155;135;227m> Running module adapt_prompt_template with input: \n",
      "task: Tom needs to buy ingredients for a spaghetti dinner he's planning for himself and a friend. He already has pasta at home but needs to buy tomato sauce and ground beef. At the store, tomato sauce costs...\n",
      "selected_modules: assistant: 2. Make a list of ideas for solving this problem, and apply them one by one to the problem to see if any progress can be made.\n",
      "9. How can I break down this problem into smaller, more manage...\n",
      "\n",
      "\u001b[0m\u001b[1;3;38;2;155;135;227m> Running module adapt_llm with input: \n",
      "messages: Without working out the full solution, adapt the following reasoning modules to be specific to our task:\n",
      "2. Make a list of ideas for solving this problem, and apply them one by one to the problem to s...\n",
      "\n",
      "\u001b[0m\u001b[1;3;38;2;155;135;227m> Running module implement_prompt_template with input: \n",
      "task: Tom needs to buy ingredients for a spaghetti dinner he's planning for himself and a friend. He already has pasta at home but needs to buy tomato sauce and ground beef. At the store, tomato sauce costs...\n",
      "adapted_modules: assistant: 2. Some ideas for solving this problem could include: calculating the total cost of the items Tom needs to buy, subtracting this total from the $50 bill he pays with, or breaking down the p...\n",
      "\n",
      "\u001b[0m\u001b[1;3;38;2;155;135;227m> Running module implement_llm with input: \n",
      "messages: Without working out the full solution, create an actionable reasoning structure for the task using these adapted reasoning modules:\n",
      "2. Some ideas for solving this problem could include: calculating th...\n",
      "\n",
      "\u001b[0m\u001b[1;3;38;2;155;135;227m> Running module reasoning_prompt_template with input: \n",
      "task: Tom needs to buy ingredients for a spaghetti dinner he's planning for himself and a friend. He already has pasta at home but needs to buy tomato sauce and ground beef. At the store, tomato sauce costs...\n",
      "reasoning_structure: assistant: 1. Identify the problem: The problem is to calculate the change Tom should receive after purchasing the items he needs for his spaghetti dinner.\n",
      "\n",
      "2. Identify the relevant data: The cost of ...\n",
      "\n",
      "\u001b[0m\u001b[1;3;38;2;155;135;227m> Running module reasoning_llm with input: \n",
      "messages: Using the following reasoning structure: 1. Identify the problem: The problem is to calculate the change Tom should receive after purchasing the items he needs for his spaghetti dinner.\n",
      "\n",
      "2. Identify t...\n",
      "\n",
      "\u001b[0m"
     ]
    }
   ],
   "source": [
    "task = \"Tom needs to buy ingredients for a spaghetti dinner he's planning for himself and a friend. He already has pasta at home but needs to buy tomato sauce and ground beef. At the store, tomato sauce costs $3 per jar and ground beef costs $5 per pound. Tom buys 2 jars of tomato sauce and 2 pounds of ground beef. He also picks up a loaf of bread for $2.50. If Tom pays with a $50 bill, how much change should he receive after purchasing these items?\"\n",
    "output = self_discover_pack.run(task)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "assistant: 1. Identify the problem: The problem is to calculate the change Tom should receive after purchasing the items he needs for his spaghetti dinner.\n",
      "\n",
      "2. Identify the relevant data: The cost of each item Tom needs to buy is $3 per jar of tomato sauce, $5 per pound of ground beef, and $2.50 for a loaf of bread. Tom buys 2 jars of tomato sauce and 2 pounds of ground beef. He pays with a $50 bill.\n",
      "\n",
      "3. Break down the problem: Calculate the cost of each item separately, then add these costs together to get the total cost of the items.\n",
      "\n",
      "4. Calculate the total cost: Multiply the price per jar of tomato sauce ($3) by the number of jars Tom buys (2), which equals $6. Multiply the price per pound of ground beef ($5) by the number of pounds Tom buys (2), which equals $10. Add the cost of the bread ($2.50) to these totals. The total cost is $6 + $10 + $2.50 = $18.50.\n",
      "\n",
      "5. Subtract the total cost from the amount paid: Subtract the total cost of the items ($18.50) from the $50 bill Tom pays with. The result is $50 - $18.50 = $31.50.\n",
      "\n",
      "6. Determine the change: The result of the subtraction is the amount of change Tom should receive. Tom should receive $31.50 in change.\n",
      "\n",
      "7. Verify the solution: Check that the calculated change is a reasonable amount and that no steps were missed in the calculation process. The change of $31.50 seems reasonable given the cost of the items and the amount Tom paid with. No steps appear to have been missed in the calculation. Therefore, the solution is correct. Tom should receive $31.50 in change.\n"
     ]
    }
   ],
   "source": [
    "print(output)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "llama",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3"
  },
  "vscode": {
   "interpreter": {
    "hash": "b1d2a638b53f4d7129cb7686d8e3b97ae1d80a593a1618479f60cef5591ea888"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
